#include "Buffer.hpp"


Buffer::Buffer(int size): capacity_(size)
{
    data_ = (char*) malloc(size);
    bzero(data_, size);
}

Buffer::~Buffer() {
    if (data_ != nullptr)free(data_);
}


void Buffer::extendRoom(int size) {
    if (writableSize() >= size) {
        return;
    }
    else if (readPos_ + writableSize() >= size) {
        int readable = readableSize();
        memcpy(data_, data_ + readPos_, readable);
        readPos_ = 0;
        writePos_ = readable;
    }
    else {
        void* temp = realloc(data_, capacity_ + size);
        if (temp == NULL) {
            return;
        }
        memset(temp + capacity_, 0, size);
        data_ = static_cast<char*>(temp);
        capacity_ += size;
    }

}


int Buffer::appendString(const char* data, int size) {
    if (data == nullptr || size <= 0) {
        return -1;
    }
    extendRoom(size);
    memcpy(data_+writePos_, data, size);
    writePos_ += size;
    return 0;
}

int Buffer::appendString(const char* data) {
    int size = strlen(data);
    int ret = appendString(data, size);
    return ret;
}


// std::vector<char> Buffer::getData(int size){
//     if (size < 0) {
//         return std::vector<char> ();
//     }
//     int readable = readableSize();
//     if (size > readable) {
//         size = readable;
//     }
//     std::vector<char> result(data_+readPos_, data_+readPos_+size);
//     readPos_ += size;
//     return result;
// }



// std::vector<char> Buffer::getData() {
//     return getData(readableSize());
// }



// std::vector<char> Buffer::getSplit(const char* needle, int needleSize) {
//     char* ptr = static_cast<char*>(memmem(data_+readPos_, readableSize(), needle, needleSize));
//     if (ptr == NULL) {
//         return std::vector<char>(data_+readPos_, data_+readPos_+readableSize());
//     }
//     std::vector<char> result(data_+readPos_, ptr);
//     readPos_ = ptr - data_ + needleSize;
//     return result;
// }





int Buffer::socketRead(int fd) {
    struct iovec vec[2];// #include <sys/uio.h>
    int writable = writableSize();
    vec[0].iov_base = data_ + writePos_;
    vec[0].iov_len = writable;
    
    char* tmpbuf = (char*) malloc(40960);
    vec[1].iov_base = tmpbuf;
    vec[1].iov_len = 40960;

    int result = readv(fd, vec, 2); // 返回读了多少字节。
    if (result == -1) {
        return -1;
    }
    else if (result <= writable) {
        writePos_ += result;
    }
    else {
        writePos_ = capacity_;
        appendString(tmpbuf, result - writable);
    }
    free(tmpbuf);
    return result;
}


const char* Buffer::findCRLF(const char* needle, int needleSize) {
    char* ptr = static_cast<char*>(memmem(data_+readPos_, readableSize(), needle, needleSize));
    return ptr;
}


int Buffer::sendData(int socket) {
    int readable = readableSize();
    if (readable > 0) {
        int count = send(socket, data_+readPos_, readable, MSG_NOSIGNAL);
        if (count > 0) {
            readPos_ += count;
            // usleep(1);
        }
        return count;
    }
    return 0;
}



